#include <stdlib.h>
#include <assert.h>
#include "node.h"
#include "edge.h"

node node_create(unsigned int name){
	node nd = NULL;
	nd = (node) malloc(sizeof(struct s_node));
	if (nd != NULL){
        nd->name = name;
        nd->visited = false;
        nd->neighbours = plist_create();
    }
	return nd;
}

int node_get_level(node nd){
    return nd->level;
}

void node_set_level(node nd, int level){
    nd->level = level;
}

bool node_visited(node nd){
	assert(nd != NULL);
	return nd->visited;
}

plist_t node_neighbours(node nd){
	assert(nd != NULL);
    plist_rewind(nd->neighbours);
    return nd->neighbours;
}

node node_destroy(node nd){
    assert(nd!=NULL);
	plist_destroy(&nd->neighbours);
	free(nd);
    return NULL;
}

void node_visit(node nd){
	assert(nd != NULL);
	nd->visited = true;
}

void node_unvisit(node nd){
	assert(nd != NULL);
	nd->visited = false;
}

unsigned int node_name (node nd){
	assert(nd != NULL);
	return nd->name;
}

void node_add_neighbour(node nd, node to, unsigned int capacity, unsigned int flow, int level, bool backward){
    edge e = NULL;
    assert(nd != NULL);
    e = edge_create(to,capacity,flow,backward);
	if(e != NULL){
        plist_append(nd-> neighbours, e);
	}
}

bool node_neighbours_fordward(node nd){
    bool ret = false;
    edge e = NULL;
    assert(nd != NULL);
    assert(nd->neighbours!=NULL);

    plist_rewind(nd->neighbours);
    e = plist_get_next(nd->neighbours);
    
    /* Recorremos los vecinos del nodo para ver si hay algun vecino, 
     * ya sea backward o forward*/
    while (e != NULL && !ret){
        
        /* Si hay uno devolvemos true*/
        if ((!edge_get_backward(e) && edge_get_capacity(e)-edge_get_flow(e) > 0) || (edge_get_backward(e) && edge_get_flow(e) > 0 ))
            ret = true;
        e = plist_get_next(nd->neighbours);
    }
    
    plist_rewind(nd->neighbours);
    return ret;
}

void node_delete_neighbour(node nd, unsigned int name){
    /* La nueva lista de vecinos del nodo*/
    plist_t new_neighbours = plist_create();
    edge e = NULL;
    assert(nd != NULL);
    assert(nd->neighbours!=NULL);
    
    plist_rewind(nd->neighbours);
    e = plist_get_next(nd->neighbours);
    
    /* Recorro los vecinos y los agrego a la nueva lista, si su nombre
     * no es name */
    while ( e != NULL){
        if (node_name(edge_to(e)) != name){
            plist_append(new_neighbours, e);
        }
        e = plist_get_next(nd->neighbours);
    }
    
    /* Remplazo la lista anterior */
    nd->neighbours = new_neighbours;
    plist_rewind(nd->neighbours);
}

node node_get_neighbour(node nd){
    edge e = NULL;
    assert(nd != NULL);
    plist_rewind(nd->neighbours);
    e = plist_get_next(nd->neighbours);
    
    /* Recorremos los vecinos del nodo para ver si hay algun vecino, 
     * ya sea backward o forward*/
    while ( e != NULL){
        
        /* Si hay uno devolvemos el nodo*/
        if ((!edge_get_backward(e) && edge_get_capacity(e)-edge_get_flow(e) > 0) || (edge_get_backward(e) && edge_get_flow(e) > 0) ){
            plist_rewind(nd->neighbours);
            return edge_to(e);
        }
        e = plist_get_next(nd->neighbours);
    }
    plist_rewind(nd->neighbours);
    return NULL;
}






